with sharing global class MedicalIncrementalChangesWS {

    global class WebToPDAMedical{
        webservice List<Hospital__c> NeedInsertHospital;
        webservice List<Hospital__c> NeedUpdateHospital;
        webservice List<HCP__c> NeedInsertHCP;
        webservice List<HCP__c> NeedUpdateHCP;
        webservice List<id> NeedDelHospital;
        webservice List<id> NeedDelHCP;
        webservice Boolean ResetPDA;
        webservice string debugNum; //debug
    }
    
    global class inputClass{
        webservice Boolean downloadAll;
    }
    static String HospitalIn = 'HospitalIn';
    static String HcpIn = 'HcpIn';

    static List<PDAMasterDataBackup__c> DeletePDAMasterData = new List<PDAMasterDataBackup__c>();
    static List<PDAMasterDataBackup__c> InsertPDAMasterData = new List<PDAMasterDataBackup__c>();
    
    
   @future(callout = true)
    public static void UpdatePDAMasterData()
    {
        List<PDAMasterDataBackup__c> InsertPDAMasterDatas = new List<PDAMasterDataBackup__c>();
        delete [Select CreatedDate,id From PDAMasterDataBackup__c where OwnerId  =: UserInfo.getUserId()];

        List<Hospital__c> UpdateHosLists = [Select class__c,IsConfirm__c, HospitalCode__c, Nickname__c,effectivedate__c, Id, Name, type1__c, 
                             OwnerId,Isdeleted,Active__c,approvaltype__c from Hospital__c where Active__c = true or approvalstatus__c = '审批通过但未生效'];
        List<HCP__c> UpdateHcpLists = [Select class1__c,class2__c,Active__c,effectivedate__c, class3__c,IsDeleted, Dept__c, approvaltype__c,
                            HCPCode__c, Hospital__c,Id,Name,Hospital__r.effectivedate__c,Hospital__r.OwnerId,Hospital__r.Active__c from HCP__c 
                            where Active__c = true or approvalstatus__c = '审批通过但未生效' limit 3000];  



                              
        for(Hospital__c hos :UpdateHosLists ){
            PDAMasterDataBackup__c pdaHos = new PDAMasterDataBackup__c(ID__c = hos.id, Type__c = 'Hospital_M');
            InsertPDAMasterDatas.add(pdaHos);
        }
        for(HCP__c hcp :UpdateHcpLists ){
            PDAMasterDataBackup__c pdaHcp = new PDAMasterDataBackup__c(ID__c = hcp.id, Type__c = 'HCP');
            InsertPDAMasterDatas.add(pdaHcp);
        }
        insert InsertPDAMasterDatas;   
    }


// get all data
// ResetOrNot is true. 1. clear the PDA, 2. get all data
// ResetOrNot is false. get all data   
    public static WebToPDAMedical ReturnAllData(Boolean ResetOrNot)
    {
        List<Hospital__c> UpdateHosList = new List<Hospital__c>(); 
        List<HCP__c> UpdateHcpList = new List<HCP__c>();        
        List<id> DeleteHosList = new List<id>();
        List<id> DeleteHcpList = new List<id>();

        
        //init WebToPDAMedical data
        WebToPDAMedical ReturnBack = new WebToPDAMedical();
        ReturnBack.ResetPDA = ResetOrNot;

        UpdateHosList = [Select class__c,IsConfirm__c, HospitalCode__c, Nickname__c,effectivedate__c, Id, Name, type1__c, 
                             OwnerId,Isdeleted,Active__c,approvaltype__c from Hospital__c where Active__c = true or approvalstatus__c = '审批通过但未生效'];
        UpdateHcpList = [Select class1__c,class2__c,Active__c,effectivedate__c, class3__c,IsDeleted, Dept__c, approvaltype__c,
                            HCPCode__c, Hospital__c,Id,Name,Hospital__r.effectivedate__c,Hospital__r.OwnerId,Hospital__r.Active__c  from HCP__c 
                            where Active__c = true or approvalstatus__c = '审批通过但未生效'];

                          
        DeletePDAMasterData  = [Select CreatedDate,id From PDAMasterDataBackup__c];
        for(Hospital__c hos :UpdateHosList){
            PDAMasterDataBackup__c pdaHos = new PDAMasterDataBackup__c(ID__c = hos.id, Type__c = 'Hospital_M');
            InsertPDAMasterData.add(pdaHos);
        }
        for(HCP__c hcp :UpdateHcpList ){
            PDAMasterDataBackup__c pdaHcp = new PDAMasterDataBackup__c(ID__c = hcp.id, Type__c = 'HCP');
            InsertPDAMasterData.add(pdaHcp);
        }
        UpdatePDAMasterData();
        
        ReturnBack.NeedInsertHospital = UpdateHosList;
        ReturnBack.NeedInsertHCP = UpdateHcpList;
        
        return ReturnBack;   
    }

    // get approval data
    public static List<Id> GetApprovalHistory(List<id> ids,String input,datetime updateDate)
    {
        List<id> returnIds = new List<id>();
        List<String> HosApprovalNames = new List<String>();
        HosApprovalNames.add('医院重命名');
        HosApprovalNames.add('改变医院级别');
        List<String> HcpApprovalNames = new List<String>();
        HcpApprovalNames.add('改变医护人员级别');
         
        if(input == HospitalIn)
        {
            if(ids.size() >0){
             List<HospitalChangeHistory__c> HospitalHistoryNeed = [Select id,Hospital__c From HospitalChangeHistory__c Where
                                                         Hospital__c in: ids
                                                         and CreatedDate >=: updateDate - 1
                                                         and Name in: HosApprovalNames];
             for(HospitalChangeHistory__c hos : HospitalHistoryNeed )
             {
                 returnIds.add(hos.Hospital__c);
             }                                            
            }         
        }
        if(input == HcpIn)
        {
            if(ids.size() >0){
             List<HCPChangeHistory__c > HCPHistoryNeed = [Select id,HCP__c From HCPChangeHistory__c Where
                                                         HCP__c in: ids
                                                         and CreatedDate >=: updateDate -1 
                                                         and Name in: HcpApprovalNames ];
             for(HCPChangeHistory__c hcp : HCPHistoryNeed)
             {
                 returnIds.add(hcp.HCP__c);
             }
            }          
        }
        return returnIds;
    }


// main function  
    webService static WebToPDAMedical getIncrementalMedical(inputClass FromPDA)
    {
        List<Hospital__c> InsertHosList = new List<Hospital__c>();
        List<Hospital__c> UpdateHosList = new List<Hospital__c>();
        List<id> DeleteHosList = new List<id>();
        List<HCP__c> InsertHcpList = new List<HCP__c>();
        List<HCP__c> UpdateHcpList = new List<HCP__c>();
        List<id> DeleteHcpList = new List<id>();
        
        //init WebToPDAMedical data
        WebToPDAMedical ReturnBack = new WebToPDAMedical();
        ReturnBack.ResetPDA = false;
        
        if(FromPDA.downloadAll)
        {
            ReturnBack = ReturnAllData(false);
            ReturnBack.debugNum = 'first time call in'; // debug
            return ReturnBack;
        }
        else
        {
            List<PDAMasterDataBackup__c> ExistPDAMasterData = [Select CreatedDate,id,Type__c,ID__c From PDAMasterDataBackup__c Where OwnerId  =: UserInfo.getUserId()];
            if(ExistPDAMasterData.size() <= 0)
            {
                ReturnBack = ReturnAllData(true); // web have no backupdata, but PDA have . PDA need reset data.
                ReturnBack.debugNum = 'no data in back up table'; // debug
                return ReturnBack;
            }  
            
            datetime updateTime = ExistPDAMasterData[0].CreatedDate; // get last time
            
            DeletePDAMasterData = ExistPDAMasterData;
            List<PDAMasterDataBackup__c> ExistHos = new List<PDAMasterDataBackup__c>();
            List<PDAMasterDataBackup__c> ExistHcp = new List<PDAMasterDataBackup__c>();
            List<id> ExistHosIds = new List<id>();
            List<id> ExistHcpIds = new List<id>();


            Map<id,PDAMasterDataBackup__c> mapExistHos = new Map<Id,PDAMasterDataBackup__c>();
            Map<id,PDAMasterDataBackup__c> mapClearExistHos = new Map<Id,PDAMasterDataBackup__c>();
            Map<id,PDAMasterDataBackup__c> mapExistHcp = new Map<Id,PDAMasterDataBackup__c>(); 
            Map<id,PDAMasterDataBackup__c> mapClearExistHcp = new Map<Id,PDAMasterDataBackup__c>();
                                    
            for(PDAMasterDataBackup__c p : ExistPDAMasterData )
            {
                if(p.Type__c == 'Hospital_M')
                {
                    ExistHos.add(p);
                    ExistHosIds.add(p.ID__c);
                    mapExistHos.put(p.ID__c,p);
                    mapClearExistHos.put(p.ID__c,p);
                }
                else if(p.Type__c == 'HCP')
                {
                    ExistHcp.add(p);
                    ExistHcpIds.add(p.ID__c);
                    mapExistHcp.put(p.ID__c,p);
                    mapClearExistHcp.put(p.ID__c,p);
                } 
            }
            
// Hospital process

            List<Hospital__c> HaveSeenHos = [Select class__c,IsConfirm__c, HospitalCode__c, Nickname__c,effectivedate__c, Id, Name, type1__c, 
                             OwnerId,Isdeleted,Active__c,approvaltype__c from Hospital__c where Active__c = true or approvalstatus__c = '审批通过但未生效'];
            
            Map<id,Hospital__c> mapHaveSeenHos = new Map<Id,Hospital__c>(HaveSeenHos); 

            
// HCP process

            List<HCP__c> HaveSeenHcp = [Select class1__c,class2__c,Active__c,effectivedate__c, class3__c,IsDeleted, Dept__c,approvaltype__c, 
                            HCPCode__c, Hospital__c,Id,Name,Hospital__r.effectivedate__c,Hospital__r.OwnerId,Hospital__r.Active__c from HCP__c 
                            where Active__c = true or approvalstatus__c = '审批通过但未生效' limit 2000];           
            Map<id,HCP__c> mapHaveSeenHcp = new Map<Id,HCP__c>(HaveSeenHcp);

            
            // add delete hcp
            for(PDAMasterDataBackup__c p : ExistHcp){              
                if(!mapHaveSeenHcp.containsKey(p.ID__c)){
                    DeleteHcpList.add(p.ID__c);
                    mapClearExistHcp.remove(p.id);
                }                     
            }
            // add insert hcp
            for(HCP__c h : HaveSeenHcp){
                if(!mapExistHcp.containsKey(h.id)){
                    InsertHcpList.add(h);
                    mapClearExistHcp.remove(h.id);  
                }
            }
            // add update hcp

            
// Hospital process            

            // add delete hospital
            for(PDAMasterDataBackup__c p :ExistHos){              
                if(!mapHaveSeenHos.containsKey(p.ID__c)){
                    DeleteHosList.add(p.ID__c);
                    mapClearExistHos.remove(p.id);    
                }                     
            }
            
            // add insert hospital
            for(Hospital__c h : HaveSeenHos){
                if(!mapExistHos.containsKey(h.id)){
                    ReturnBack.debugNum = h.id; // debug
                    InsertHosList.add(h);
                }
            }
            
            // add update hospital       
            List<id> clearExitHos = new List<id>();
            List<id> clearExitHcp = new List<id>();
            
            for(PDAMasterDataBackup__c p : mapClearExistHos.values()){
                clearExitHos.add(p.ID__c);
            }
            for(PDAMasterDataBackup__c p : mapClearExistHcp.values()){
                clearExitHcp.add(p.ID__c);
            }
                    

            List<Id> getFromApprovalHos = GetApprovalHistory(clearExitHos, HospitalIn, updateTime);
            // add update from hospital approval
            if(getFromApprovalHos.size()>0){
                UpdateHosList = [Select class__c,IsConfirm__c, HospitalCode__c, Nickname__c,effectivedate__c, Id, Name, type1__c, 
                                 OwnerId, Isdeleted,Active__c,approvaltype__c From Hospital__c 
                                 Where id in: getFromApprovalHos];
            }                 
                             
            // add update from hcp approval
            List<Id> getFromApprovalHcp = GetApprovalHistory(clearExitHcp, HcpIn, updateTime);
            if(getFromApprovalHos.size()>0){
                UpdateHcpList = [Select class1__c,class2__c,Active__c,effectivedate__c, class3__c,IsDeleted, Dept__c, 
                                 HCPCode__c, Hospital__c,Id,Name,Hospital__r.effectivedate__c,Hospital__r.OwnerId,Hospital__r.Active__c from HCP__c 
                                 Where id in: getFromApprovalHcp];
            }                 

            for(Hospital__c hos : InsertHosList)
            {
                PDAMasterDataBackup__c pdaHos = new PDAMasterDataBackup__c(ID__c = hos.id, Type__c = 'Hospital_M');
                InsertPDAMasterData.add(pdaHos);
            }
            for(Hospital__c hos : UpdateHosList)
            {
                PDAMasterDataBackup__c pdaHos = new PDAMasterDataBackup__c(ID__c = hos.id, Type__c = 'Hospital_M');
                InsertPDAMasterData.add(pdaHos);
            }            
            for(HCP__c hcp :InsertHcpList){
                PDAMasterDataBackup__c pdaHcp = new PDAMasterDataBackup__c(ID__c = hcp.id, Type__c = 'HCP');
                InsertPDAMasterData.add(pdaHcp);
            }
            for(HCP__c hcp :UpdateHcpList){
                PDAMasterDataBackup__c pdaHcp = new PDAMasterDataBackup__c(ID__c = hcp.id, Type__c = 'HCP');
                InsertPDAMasterData.add(pdaHcp);
                ReturnBack.debugNum = 'add HCP id';
            }
            if(InsertPDAMasterData.size() > 0){
                UpdatePDAMasterData();
            }        

            ReturnBack.NeedInsertHospital = InsertHosList;
            ReturnBack.NeedUpdateHospital = UpdateHosList;
            ReturnBack.NeedDelHospital = DeleteHosList;
            ReturnBack.NeedInsertHCP = InsertHcpList;
            ReturnBack.NeedUpdateHCP = UpdateHcpList;
            ReturnBack.NeedDelHCP = DeleteHcpList;
            //ReturnBack.debugNum = 'run last'; // debug
            return ReturnBack;                       
                    
        }
    }     
     /*
     //test class
     static testMethod void testMedicalIncrementalChangesWS () {
        User u = [Select id From User Where Title__c = 'Sales Rep' and FunctionDepartment__c = 'Medical Sales' and IsActive =: true limit 1];
         System.runAs(u ) {
             MedicalIncrementalChangesWS.inputClass input = new MedicalIncrementalChangesWS.inputClass();
             //input.downloadAll = true;
             //MedicalIncrementalChangesWS.getIncrementalMedical(input);
             input.downloadAll = false;
             MedicalIncrementalChangesWS.getIncrementalMedical(input);
         }
     }*/
}